import { useControlController, useNamespace } from '@ibiz-template/vue3-util';
import {
  ConcreteComponent,
  defineComponent,
  getCurrentInstance,
  h,
  PropType,
  reactive,
  ref,
  resolveComponent,
  VNode,
} from 'vue';
import {
  IDashboard,
  IDBContainerPortletPart,
  IDBPortletPart,
  IModelObject,
} from '@ibiz/model-core';
import './dashboard.scss';
import { DashboardController, IControlProvider } from '@ibiz-template/runtime';

/**
 * 根据类型绘制数据看板成员
 *
 * @author lxm
 * @date 2022-10-14 17:10:42
 * @param {PortletPartModel} model 模型
 * @param {IData} opts 额外参数
 */
function renderPortletByType(
  model: IDBPortletPart,
  c: DashboardController,
  opts?: IData,
): VNode {
  const provider = c.providers[model.id!];
  const controller = c.portlets[model.id!];
  const commonProps = {
    modelData: model,
    controller,
  };

  if (!provider) {
    return (
      <div>
        {model.portletType}
        {ibiz.i18n.t('app.noSupport')}
      </div>
    );
  }

  const providerComp = resolveComponent(
    provider.component,
  ) as ConcreteComponent;
  // 绘制容器
  if (model.portletType === 'CONTAINER') {
    const container = model as IDBContainerPortletPart;
    return h(
      providerComp,
      {
        ...commonProps,
        key: model.id,
      },
      {
        default: () =>
          container.controls?.map(child => renderPortletByType(child, c, opts)),
      },
    );
  }

  // 绘制门户部件
  return h(providerComp, {
    ...commonProps,
    key: model.id,
  });
}

export const DashboardControl = defineComponent({
  name: 'IBizDashboardControl',
  props: {
    modelData: {
      type: Object as PropType<IDashboard>,
      required: true,
    },
    context: { type: Object as PropType<IContext>, required: true },
    params: { type: Object as PropType<IParams>, default: () => ({}) },
    provider: { type: Object as PropType<IControlProvider> },
  },
  setup() {
    const c = useControlController(
      (...args) => new DashboardController(...args),
    );

    const vue = getCurrentInstance()!.proxy!;

    // 自定义门户模型数组
    const customModelDatas = ref([]);

    const ns = useNamespace(`control-${c.model.controlType!.toLowerCase()}`);

    c.evt.on('onCreated', () => {
      // 数据看板成员state响应式
      Object.values(c.portlets).forEach(portlet => {
        portlet.state = reactive(portlet.state);
      });
    });

    // 处理自定义布局数据改变
    const handleCustomModelChange = async (args: IData) => {
      customModelDatas.value = args.model;
      await c.initPortlets(customModelDatas.value);
      vue.$forceUpdate();
    };

    return { c, ns, customModelDatas, handleCustomModelChange };
  },

  render() {
    const { state, model } = this.c;

    const renderDefaultContent = () => {
      return (
        <iBizRow class={[this.ns.b()]} layout={model.layout}>
          {model.controls?.map((child: IDBPortletPart) => {
            return (
              <iBizCol
                layoutPos={child.layoutPos}
                state={this.c.portlets[child.id!]?.state}
              >
                {renderPortletByType(child, this.c)}
              </iBizCol>
            );
          })}
        </iBizRow>
      );
    };

    const renderCustomSlots = () => {
      const slots: IData = {
        default: () => {
          return renderDefaultContent();
        },
      };
      this.customModelDatas.forEach((item: IModelObject) => {
        slots[item.codeName!] = () => renderPortletByType(item, this.c);
      });
      return slots;
    };

    return (
      <iBizControlBase controller={this.c} class={[this.ns.b()]}>
        {state.isCreated &&
          (model.enableCustomized ? (
            <iBizCustomDashboardContainer
              modelData={this.modelData}
              dashboard={this.c}
              onChanged={this.handleCustomModelChange}
            >
              {renderCustomSlots()}
            </iBizCustomDashboardContainer>
          ) : (
            renderDefaultContent()
          ))}
      </iBizControlBase>
    );
  },
});
